
<!DOCTYPE html>
<html lang="zh-Hans" class="loading">
<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>学习react.js比你想象的简单 - 默默默默燃</title>
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <meta name="google" content="notranslate" />
    <meta name="keywords" content="TriDiamond Obsidian,"> 
    <meta name="description" content="一枚前端搬砖队队员的记录册,原文地址

学习 React.js 比你想象的要简单
React 全部都是组件化的React 是围绕可重用组件的概念设计的。你定义小组件并将它们组合在一起形成更大的组件。
无论大小，所有组件都是可重,"> 
    <meta name="author" content="张白告丶"> 
    <link rel="alternative" href="atom.xml" title="默默默默燃" type="application/atom+xml"> 
    <link rel="icon" href="/img/favicon.png"> 
    <link href="https://fonts.loli.net/css?family=Roboto+Mono|Rubik&display=swap" rel="stylesheet">
    
<link rel="stylesheet" href="//at.alicdn.com/t/font_1429596_nzgqgvnmkjb.css">

    
<link rel="stylesheet" href="//cdn.bootcss.com/animate.css/3.7.2/animate.min.css">

    
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/social-share.js/1.0.16/css/share.min.css">

    
<link rel="stylesheet" href="//cdn.bootcss.com/codemirror/5.48.4/codemirror.min.css">

    
<link rel="stylesheet" href="//cdn.bootcss.com/codemirror/5.48.4/theme/dracula.css">

    
<link rel="stylesheet" href="/css/obsidian.css">

    
<link rel="stylesheet" href="/css/ball-atom.min.css">

<meta name="generator" content="Hexo 4.2.0"></head>


<body class="loading">
    <div class="loader">
        <div class="la-ball-atom la-2x">
            <div></div>
            <div></div>
            <div></div>
            <div></div>
        </div>
    </div>
    <span id="config-title" style="display:none">默默默默燃</span>
    <div id="loader"></div>
    <div id="single">
    <div class="scrollbar gradient-bg-rev"></div>
<div id="top" style="display: block;">
    <div class="bar" style="width: 0;"></div>
    <div class="navigation animated fadeIn fast delay-1s">
        <img id="home-icon" class="icon-home" src="/img/favicon.png" alt="" data-url="https://zhanghao-web.github.io">
        <div id="play-icon" title="Play/Pause" class="iconfont icon-play"></div>
        <h3 class="subtitle">学习react.js比你想象的简单</h3>
        <div class="social">
            <!--        <div class="like-icon">-->
            <!--            <a href="javascript:;" class="likeThis active"><span class="icon-like"></span><span class="count">76</span></a>-->
            <!--        </div>-->
            <div>
                <div class="share">
                    
                        <a href="javascript:;" class="iconfont icon-share1"></a>
                        <div class="share-component-cc" data-disabled="facebook,douban,linkedin,diandian,tencent,google"></div>
                    
                </div>
            </div>
        </div>
    </div>
</div>

    <div class="section">
        <div class=article-header-wrapper>
    <div class="article-header">
        <div class="article-cover animated fadeIn" style="
            animation-delay: 600ms;
            animation-duration: 1.2s;
            background-image: 
                radial-gradient(ellipse closest-side, rgba(0, 0, 0, 0.65), #100e17),
                url(/img/cover.jpg) ">
        </div>
        <div class="else">
            <p class="animated fadeInDown">
                
                <a href="/categories/React"><b>「
                    </b>REACT<b> 」</b></a>
                
                March 03, 2018
            </p>
            <h3 class="post-title animated fadeInDown"><a href="/2018/03/03/React/%E5%AD%A6%E4%B9%A0react-js%E6%AF%94%E4%BD%A0%E6%83%B3%E8%B1%A1%E7%9A%84%E7%AE%80%E5%8D%95/" title="学习react.js比你想象的简单" class="">学习react.js比你想象的简单</a>
            </h3>
            
            <p class="post-count animated fadeInDown">
                
                <span>
                    <b class="iconfont icon-text2"></b> <i>Words count</i>
                    39k
                </span>
                
                
                <span>
                    <b class="iconfont icon-timer__s"></b> <i>Reading time</i>
                    35 mins.
                </span>
                
                
                
                <span id="busuanzi_container_page_pv">
                    <b class="iconfont icon-read"></b> <i>Read count</i>
                    <span id="busuanzi_value_page_pv">0</span>
                </span>
                
            </p>
            
            
            <ul class="animated fadeInDown post-tags-list" itemprop="keywords"><li class="animated fadeInDown post-tags-list-item"><a class="animated fadeInDown post-tags-list-link" href="/tags/React/" rel="tag">React</a></li></ul>
            
        </div>
    </div>
</div>

<div class="screen-gradient-after">
    <div class="screen-gradient-content">
        <div class="screen-gradient-content-inside">
            <div class="bold-underline-links screen-gradient-sponsor">
                <p>
                    <span class="animated fadeIn delay-1s"></span>
                </p>
            </div>
        </div>
    </div>
</div>

<div class="article">
    <div class='main'>
        <div class="content markdown animated fadeIn">
            <p><a href="https://juejin.im/post/599156cc6fb9a03c3a25db08" target="_blank" rel="noopener">原文地址</a></p>
<hr>
<h1 id="学习-React-js-比你想象的要简单"><a href="#学习-React-js-比你想象的要简单" class="headerlink" title="学习 React.js 比你想象的要简单"></a>学习 React.js 比你想象的要简单</h1><p><img src="https://user-gold-cdn.xitu.io/2017/8/14/88e06ce88c09c77c1504b772f5801686?imageView2/1/w/1304/h/734/q/85/format/webp/interlace/1" alt="react"></p>
<h2 id="React-全部都是组件化的"><a href="#React-全部都是组件化的" class="headerlink" title="React 全部都是组件化的"></a>React 全部都是组件化的</h2><p>React 是围绕可重用组件的概念设计的。你定义小组件并将它们组合在一起形成更大的组件。</p>
<p>无论大小，所有组件都是可重用的，甚至在不同的项目中也是如此。</p>
<p>React 组件最简单的形式，就是一个普通的 JavaScript 函数：<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Button</span> (<span class="params">props</span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 这里返回一个 DOM 元素，例如：</span></span><br><span class="line">  <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">"submit"</span>&gt;</span>&#123;props.label&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 将按钮组件呈现给浏览器</span></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag">&lt;<span class="name">Button</span> <span class="attr">label</span>=<span class="string">"Save"</span> /&gt;</span></span>, mountNode)</span><br></pre></td></tr></table></figure><br>例 1：编辑上面的代码并按 Ctrl+Enter 键执行（译者注：译文暂时没有这个功能，请访问原文使用此功能，下同）</p>
<blockquote>
<p>括号中的 button 标签将稍后解释。现在不要担心它们。ReactDOM 也将稍后解释，但如果你想测试这个例子和所有接下来的例子，上述 render 函数是必须的。（React 将要接管和控制的是 ReactDOM.render 的第 2 个参数即目标 DOM 元素）。在 jsComplete REPL 中，你可以使用特殊的变量 mountNode。</p>
</blockquote>
<p>例 1 的注意事项：</p>
<blockquote>
<ul>
<li><p>组件名称首字母大写，Button。必须要这样做是因为我们将处理 HTML 元素和 React 元素的混合。小写名称是为 HTML 元素保留的。事实上，将 React 组件命名为 “button” 然后你就会发现 ReactDOM 会忽略这个函数，仅仅是将其作为一个普通的空 HTML 按钮来渲染。</p>
</li>
<li><p>每个组件都接收一个属性列表，就像 HTML 元素一样。在 React 中，这个列表被称为属性。虽然你可以将一个函数随意命名。</p>
</li>
<li><p>在上面 Button 函数组件的返回输出中，我们奇怪地写了段看上去像 HTML 的代码。这实际上既不是 JavaScript 也不是 HTML，老实说，这甚至不是 React.js。然而它非常流行，以至于成为 React 应用程序中的默认值。这就是所谓的 JSX，这是一个JavaScript 的扩展。JSX 也是一个折中方案！继续尝试并在上面的函数中返回其他 HTML 元素，看看它们是如何被支持的（例如，返回一个文本输入元素）。</p>
</li>
</ul>
</blockquote>
<a id="more"></a>
<h2 id="JSX-输出的是什么？"><a href="#JSX-输出的是什么？" class="headerlink" title="JSX 输出的是什么？"></a>JSX 输出的是什么？</h2><p>上面的例 1 可以用没有 JSX 的纯 React.js 编写，如下：<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Button</span> (<span class="params">props</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> React.createElement(</span><br><span class="line">    <span class="string">"button"</span>,</span><br><span class="line">    &#123; <span class="attr">type</span>: <span class="string">"submit"</span> &#125;,</span><br><span class="line">    props.label</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 要使用 Button，你可以这么做</span></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  React.createElement(Button, &#123; <span class="attr">label</span>: <span class="string">"Save"</span> &#125;),</span><br><span class="line">  mountNode</span><br><span class="line">);</span><br></pre></td></tr></table></figure><br>例 2：不使用 JSX 编写 React 组件</p>
<p>在 React 顶级 API 中，createElement 函数是主函数。这是你需要学习的 7 个 API 中的 1 个。React 的 API 就是这么小。</p>
<p>就像 DOM 自身有一个 document.createElement 函数来创建一个由标签名指定的元素一样，React 的 createElement 函数是一个高级函数，有和 document.createElement 同样的功能，但它也可以用于创建一个表示 React 组件的元素。当我们使用上面例 2 中的按钮组件时，我们使用的是后者。</p>
<p>不像 document.createElement，React 的 createElement 在接收第二个参数后，接收一个动态参数，它表示所创建元素的子元素。所以 createElement 实际上创建了一个树。</p>
<p>这里就是这样的一个例子：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> InputForm = React.createElement(</span><br><span class="line">  <span class="string">"form"</span>,</span><br><span class="line">  &#123; <span class="attr">target</span>: <span class="string">"_blank"</span>, <span class="attr">action</span>: <span class="string">"https://google.com/search"</span> &#125;,</span><br><span class="line">  React.createElement(<span class="string">"div"</span>, <span class="literal">null</span>, <span class="string">"Enter input and click Search"</span>),</span><br><span class="line">  React.createElement(<span class="string">"input"</span>, &#123; <span class="attr">className</span>: <span class="string">"big-input"</span> &#125;),</span><br><span class="line">  React.createElement(Button, &#123; <span class="attr">label</span>: <span class="string">"Search"</span> &#125;)</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// InputForm 使用 Button 组件，所以我们需要这样做：</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Button</span> (<span class="params">props</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> React.createElement(</span><br><span class="line">    <span class="string">"button"</span>,</span><br><span class="line">    &#123; <span class="attr">type</span>: <span class="string">"submit"</span> &#125;,</span><br><span class="line">    props.label</span><br><span class="line">  );</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 然后我们可以通过 .render 方法直接使用 InputForm</span></span><br><span class="line">ReactDOM.render(InputForm, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 3：React 创建元素的 API<br>上面例子中的一些事情值得注意：</p>
<blockquote>
<ul>
<li><p>InputForm 不是一个 React 组件；它仅仅是一个 React 元素。这就是为什么我们可以在 ReactDOM.render 中直接使用它并且可以在调用时不使用 <InputForm /> 的原因。</p>
</li>
<li><p>React.createElement 函数在前两个参数后接收了多个参数。从第3个参数开始的参数列表构成了创建元素的子项列表。</p>
</li>
<li><p>我们可以嵌套 React.createElement 调用，因为它是 JavaScript。</p>
</li>
<li><p>当这个元素不需要属性时，<font color="red">React.createElement </font>的第二个参数可以为空或者是一个空对象。</p>
</li>
<li><p>我们可以在 React 组件中混合 HTML 元素。你可以将 HTML 元素作为内置的 React 组件。</p>
</li>
<li><p>React 的 API 试图和 DOM API 一样，这就是为什么我们在 input 元素中使用 className 代替 class 的原因。我们都希望如果 </p>
</li>
<li><p>React 的 API 成为 DOM API 本身的一部分，因为，你知道，它要好得多。</p>
</li>
</ul>
</blockquote>
<p>上述的代码是当你引入 React 库的时候浏览器是怎样理解的。浏览器不会处理任何 JSX 业务。然而，我们更喜欢看到和使用 HTML，而不是那些 createElement 调用（想象一下只使用 document.createElement 构建一个网站！）。这就是 JSX 存在的原因。取代上述调用 React.createElement 的方式，我们可以使用一个非常简单类似于 HTML 的语法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> InputForm =</span><br><span class="line">  &lt;form target=<span class="string">"_blank"</span> action=<span class="string">"https://google.com/search"</span>&gt;</span><br><span class="line">    &lt;div&gt;Enter input and click Search&lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp">    &lt;input className="big-input" name="q" /</span>&gt;</span><br><span class="line">    &lt;Button label=<span class="string">"Search"</span> /&gt;</span><br><span class="line">  &lt;<span class="regexp">/form&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ InputForm “仍然”使用 Button 组件，所以我们也需要这样。</span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ JXS 或者普通的表单都会这样做</span></span><br><span class="line"><span class="regexp">function Button (props) &#123;</span></span><br><span class="line"><span class="regexp">  /</span><span class="regexp">/ 这里返回一个 DOM 元素。例如：</span></span><br><span class="line"><span class="regexp">  return &lt;button type="submit"&gt;&#123;props.label&#125;&lt;/</span>button&gt;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 然后我们可以直接通过 .render 使用 InputForm</span></span><br><span class="line">ReactDOM.render(InputForm, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 4：为什么在 React 中 JSX 受欢迎（和例 3 相比）<br>注意上面的几件事：</p>
<blockquote>
<ul>
<li>这不是 HTML 代码。比如，我们仍然可以使用 className 代替 class。</li>
<li>我们仍在考虑怎样让上述的 JavaScript 看起来像是 HTML。看一下我在最后是怎样添加的。</li>
</ul>
</blockquote>
<p>我们在上面（例 4）中写的就是 JSX。然而，我们要将编译后的版本（例 3）给浏览器。要做到这一点，我们需要使用一个预处理器将 JSX 版本转换为 React.createElement 版本。<br>这就是 JSX。这是一种折中的方案，允许我们用类似 HTML 的语法来编写我们的 React 组件，这是一个很好的方法。</p>
<blockquote>
<p>“Flux” 在头部作为韵脚来使用，但它也是一个非常受欢迎的 应用架构，由 Facebook 推广。最出名的是 Redux，Flux 和 React 非常合适。</p>
</blockquote>
<p>JSX，可以单独使用，不仅仅适用于 React。</p>
<h2 id="你可以在-JavaScript-的任何地方使用-JSX"><a href="#你可以在-JavaScript-的任何地方使用-JSX" class="headerlink" title="你可以在 JavaScript 的任何地方使用 JSX"></a>你可以在 JavaScript 的任何地方使用 JSX</h2><p>在 JSX 中，你可以在一对花括号内使用任何 JavaScript 表达式。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> RandomValue = <span class="function"><span class="params">()</span> =&gt;</span></span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &#123; <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * <span class="number">100</span>) &#125;</span><br><span class="line">  &lt;<span class="regexp">/div&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ 使用：</span></span><br><span class="line"><span class="regexp">ReactDOM.render(&lt;RandomValue /</span>&gt;, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 5：在 JSX 中使用 JavaScript 表达式</p>
<p>任何 JavaScript 表达式可以直接放在花括号中。这相当于在 JavaScript 中插入 ${} 模板。</p>
<p>这是 JSX 内唯一的约束：只有表达式。例如，你不能使用 if 语句，但三元表达式是可以的。</p>
<p>JavaScript 变量也是表达式，所以当组件接受属性列表时（不包括 RandomValue 组件，props 是可选择的），你可以在花括号里使用这些属性。我们在上述（例 1）的 Button 组件是这样使用的。</p>
<p>JavaScript 对象也是表达式。有些时候我们在花括号中使用 JavaScript 对象，这看起来像是使用了两个花括号，但是在花括号中确实只有一个对象。其中一个用例就是将 CSS 样式对象传递给响应中的特殊样式属性：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> ErrorDisplay = <span class="function">(<span class="params">&#123;message&#125;</span>) =&gt;</span></span><br><span class="line">  &lt;div style=&#123; &#123; <span class="attr">color</span>: <span class="string">'red'</span>, <span class="attr">backgroundColor</span>: <span class="string">'yellow'</span> &#125; &#125;&gt;</span><br><span class="line">    &#123;message&#125;</span><br><span class="line">  &lt;<span class="regexp">/div&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ 使用</span></span><br><span class="line"><span class="regexp">ReactDOM.render(</span></span><br><span class="line"><span class="regexp">  &lt;ErrorDisplay</span></span><br><span class="line"><span class="regexp">    message="These aren't the droids you're looking for"</span></span><br><span class="line"><span class="regexp">  /</span>&gt;,</span><br><span class="line">  mountNode</span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<p>例 6：一个对象传递特殊的 React 样式参数<br>注意我解构的只是在属性参数之外的信息。这只是 JavaScript。还要注意上面的样式属性是一个特殊的属性（同样，它不是 HTML，它更接近 DOM API）。我们使用一个对象作为样式属性的值并且这个对象定义样式就像我们使用 JavaScript </p>
<p>你可以在 JSX 中使用 React 元素。因为这也是一个表达式（记住，一个 React 元素只是一个函数调用）：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> MaybeError = <span class="function">(<span class="params">&#123;errorMessage&#125;</span>) =&gt;</span></span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &#123;errorMessage &amp;&amp; <span class="xml"><span class="tag">&lt;<span class="name">ErrorDisplay</span> <span class="attr">message</span>=<span class="string">&#123;errorMessage&#125;</span> /&gt;</span></span>&#125;</span><br><span class="line">  &lt;<span class="regexp">/div&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ MaybeError 组件使用 ErrorDisplay 组件</span></span><br><span class="line"><span class="regexp">const ErrorDisplay = (&#123;message&#125;) =&gt;</span></span><br><span class="line"><span class="regexp">  &lt;div style=&#123; &#123; color: 'red', backgroundColor: 'yellow' &#125; &#125;&gt;</span></span><br><span class="line"><span class="regexp">    &#123;message&#125;</span></span><br><span class="line"><span class="regexp">  &lt;/</span>div&gt;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 现在我们使用 MaybeError 组件：</span></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;MaybeError</span><br><span class="line">    errorMessage=&#123;<span class="built_in">Math</span>.random() &gt; <span class="number">0.5</span> ? <span class="string">'Not good'</span> : <span class="string">''</span>&#125;</span><br><span class="line">  /&gt;,</span><br><span class="line">  mountNode</span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<p>例 7：一个 React 元素是一个可以通过 {} 使用的表达式</p>
<p>上述 MaybeError 组件只会在有 errorMessage 传入或者另外有一个空的 div 才会显示 ErrorDisplay 组件。React 认为 {true}、 {false}{undefined} 和 {null} 是有效元素，不呈现任何内容。</p>
<p>我们也可以在 JSX 中使用所有的 JavaScript 的集合方法（map、reduce 、filter、 concat 等）。因为他们返回的也是表达式：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> Doubler = <span class="function">(<span class="params">&#123;value=[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]&#125;</span>) =&gt;</span></span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &#123;value.map(<span class="function"><span class="params">e</span> =&gt;</span> e * <span class="number">2</span>)&#125;</span><br><span class="line">  &lt;<span class="regexp">/div&gt;;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ 使用下面内容 </span></span><br><span class="line"><span class="regexp">ReactDOM.render(&lt;Doubler /</span>&gt;, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 8：在 {} 中使用数组</p>
<p>请注意我是如何给出上述 value 属性的默认值的，因为这全部都只是 JavaScript。注意我只是在 div 中输出一个数组表达式。React 是完全可以的。它只会在文本节点中放置每一个加倍的值。</p>
<h2 id="你可以使用-JavaScript-类写-React-组件"><a href="#你可以使用-JavaScript-类写-React-组件" class="headerlink" title="你可以使用 JavaScript 类写 React 组件"></a>你可以使用 JavaScript 类写 React 组件</h2><p>简单的函数组件非常适合简单的需求，但是有的时候我们需要的更多。React 也支持通过使用 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes" target="_blank" rel="noopener">JavaScript 类</a>来创建组件。这里 Button 组件（在例 1 中）就是使用类的语法编写的。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Button</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">button</span>&gt;</span>&#123;this.props.label&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用（相同的语法）</span></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag">&lt;<span class="name">Button</span> <span class="attr">label</span>=<span class="string">"Save"</span> /&gt;</span></span>, mountNode);</span><br></pre></td></tr></table></figure><br>例 9：使用 JavaScript 类创建组件</p>
<p>类的语法是非常简单的：定义一个扩展的 React.Component 类（另一个你需要学习的 React 的顶级 API）。该类定义了一个单一的实例函数 —— render()，并使函数返回虚拟 DOM 对象。每一次我们使用基于类的 Button 组件（例如，通过 <Button ... />）,React 将从这个基于类的组件中实例化对象，并在 DOM 树中使用该对象。</p>
<p>这就是为什么上面的例子中我们可以在 JSX 中使用 this.props.label 渲染输出的原因，因为每一个组件都有一个特殊的称为 props 的 实例 属性，这让所有的值传递给该组件时被实例化。</p>
<p>由于我们有一个与组件的单个使用相关联的实例，所以我们可以按照自己的意愿定制该实例。例如，我们可以通过使用常规 JavaScript 构造函数来构造它：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Button</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(props) &#123;</span><br><span class="line">    <span class="keyword">super</span>(props);</span><br><span class="line">    <span class="keyword">this</span>.id = <span class="built_in">Date</span>.now();</span><br><span class="line">  &#125;</span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="xml"><span class="tag">&lt;<span class="name">button</span> <span class="attr">id</span>=<span class="string">&#123;this.id&#125;</span>&gt;</span>&#123;this.props.label&#125;<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag">&lt;<span class="name">Button</span> <span class="attr">label</span>=<span class="string">"Save"</span> /&gt;</span></span>, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 10：自定义组件实例<br>我们也可以定义类的原型并且在任何我们希望的地方使用，包括在返回的 JSX 输出的内部：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Button</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  clickCounter = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">  handleClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">`Clicked: <span class="subst">$&#123;++<span class="keyword">this</span>.clickCounter&#125;</span>`</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      &lt;button id=&#123;<span class="keyword">this</span>.id&#125; onClick=&#123;<span class="keyword">this</span>.handleClick&#125;&gt;</span><br><span class="line">        &#123;<span class="keyword">this</span>.props.label&#125;</span><br><span class="line">      &lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">    );</span></span><br><span class="line"><span class="regexp">  &#125;</span></span><br><span class="line"><span class="regexp">&#125;</span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp">/</span><span class="regexp">/ 使用</span></span><br><span class="line"><span class="regexp">ReactDOM.render(&lt;Button label="Save" /</span>&gt;, mountNode);</span><br></pre></td></tr></table></figure>
<p>例 11：使用类的属性（通过单击保存按钮进行测试）</p>
<p>注意上述例 11 中的几件事情<br>handleClick 函数使用 JavaScript 新提出的 <a href="https://github.com/tc39/proposal-class-fields" target="_blank" rel="noopener">class-field syntax</a> 语法。这仍然是 stage-2，但是这是访问组件安装实例（感谢箭头函数）最好的选择（因为很多原因）。然而，你需要使用类似 Babel 的编译器解码为 stage-2（或者仅仅是类字段语法）来让上述代码工作。 jsComplete REPL 有预编译功能。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 错误：</span></span><br><span class="line">onClick=&#123;<span class="keyword">this</span>.handleClick()&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确：</span></span><br><span class="line">onClick=&#123;<span class="keyword">this</span>.handleClick&#125;</span><br></pre></td></tr></table></figure>
<h2 id="React-中的事件：两个重要的区别"><a href="#React-中的事件：两个重要的区别" class="headerlink" title="React 中的事件：两个重要的区别"></a>React 中的事件：两个重要的区别</h2><p>当处理 React 元素中的事件时，我们与 DOM API 的处理方式有两个非常重要的区别：</p>
<blockquote>
<ul>
<li>所有 React 元素属性（包括事件）都使用 camelCase 命名，而不是 lowercase。例如是 onClick 而不是 onclick。</li>
<li>我们将实际的 JavaScript 函数引用传递给事件处理程序，而不是字符串。例如是 onClick={handleClick} 而不是 onClick=”handleClick”。</li>
</ul>
</blockquote>
<p>React 用自己的对象包装 DOM 对象事件以优化事件处理的性能，但是在事件处理程序内部，我们仍然可以访问 DOM 对象上所有可以访问的方法。React 将经过包装的事件对象传递给每个调用函数。例如，为了防止表单提交默认提交操作，你可以这样做<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Form</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  handleSubmit = <span class="function">(<span class="params">event</span>) =&gt;</span> &#123;</span><br><span class="line">    event.preventDefault();</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">'Form submitted'</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      &lt;form onSubmit=&#123;<span class="keyword">this</span>.handleSubmit&#125;&gt;</span><br><span class="line">        &lt;button type=<span class="string">"submit"</span>&gt;Submit&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">      &lt;/</span>form&gt;</span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag">&lt;<span class="name">Form</span> /&gt;</span></span>, mountNode);</span><br></pre></td></tr></table></figure><br>例 12：使用包装过的对象</p>
<h2 id="每一个-React-组件都有一个故事：第-1-部分"><a href="#每一个-React-组件都有一个故事：第-1-部分" class="headerlink" title="每一个 React 组件都有一个故事：第 1 部分"></a>每一个 React 组件都有一个故事：第 1 部分</h2><p>以下仅适用于类组件（扩展 React.Component）。函数组件有一个稍微不同的故事。</p>
<h3 id="首先，我们定义了一个模板来创建组件中的元素。"><a href="#首先，我们定义了一个模板来创建组件中的元素。" class="headerlink" title="首先，我们定义了一个模板来创建组件中的元素。"></a>首先，我们定义了一个模板来创建组件中的元素。</h3><h3 id="然后，我们在某处使用-React。例如，在-render-内部调用其他的组件，或者直接使用-ReactDOM-render。"><a href="#然后，我们在某处使用-React。例如，在-render-内部调用其他的组件，或者直接使用-ReactDOM-render。" class="headerlink" title="然后，我们在某处使用 React。例如，在 render 内部调用其他的组件，或者直接使用 ReactDOM.render。"></a>然后，我们在某处使用 React。例如，在 render 内部调用其他的组件，或者直接使用 ReactDOM.render。</h3><h3 id="然后，React-实例化一个对象然后给它设置-props-然后我们可以通过-this-props-访问。这些属性都是我们在第-2-步传入的。"><a href="#然后，React-实例化一个对象然后给它设置-props-然后我们可以通过-this-props-访问。这些属性都是我们在第-2-步传入的。" class="headerlink" title="然后，React 实例化一个对象然后给它设置 props 然后我们可以通过 this.props 访问。这些属性都是我们在第 2 步传入的。"></a>然后，React 实例化一个对象然后给它设置 props 然后我们可以通过 this.props 访问。这些属性都是我们在第 2 步传入的。</h3><h3 id="因为这些全部都是-JavaScript，constructor-方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。"><a href="#因为这些全部都是-JavaScript，constructor-方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。" class="headerlink" title="因为这些全部都是 JavaScript，constructor 方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。"></a>因为这些全部都是 JavaScript，constructor 方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。</h3><h3 id="接下来-React-计算渲染之后的输出方法（虚拟-DOM-节点）。"><a href="#接下来-React-计算渲染之后的输出方法（虚拟-DOM-节点）。" class="headerlink" title="接下来 React 计算渲染之后的输出方法（虚拟 DOM 节点）。"></a>接下来 React 计算渲染之后的输出方法（虚拟 DOM 节点）。</h3><h3 id="因为这是-React-第一次渲染元素，React-将会与浏览器连通（代表我们使用-DOM-API）来显示元素。这整个过程称为-mounting。"><a href="#因为这是-React-第一次渲染元素，React-将会与浏览器连通（代表我们使用-DOM-API）来显示元素。这整个过程称为-mounting。" class="headerlink" title="因为这是 React 第一次渲染元素，React 将会与浏览器连通（代表我们使用 DOM API）来显示元素。这整个过程称为 mounting。"></a>因为这是 React 第一次渲染元素，React 将会与浏览器连通（代表我们使用 DOM API）来显示元素。这整个过程称为 mounting。</h3><h3 id="接下来-React-调用另一个生命周期函数，称为-componentDidMount。我们可以这样使用这个方法，例如：在-DOM-上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的-DOM-都是虚拟的。"><a href="#接下来-React-调用另一个生命周期函数，称为-componentDidMount。我们可以这样使用这个方法，例如：在-DOM-上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的-DOM-都是虚拟的。" class="headerlink" title="接下来 React 调用另一个生命周期函数，称为 componentDidMount。我们可以这样使用这个方法，例如：在 DOM 上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的 DOM 都是虚拟的。"></a>接下来 React 调用另一个生命周期函数，称为 componentDidMount。我们可以这样使用这个方法，例如：在 DOM 上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的 DOM 都是虚拟的。</h3><h3 id="一些组件的故事到此结束，其他组件得到卸载浏览器-DOM-中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。"><a href="#一些组件的故事到此结束，其他组件得到卸载浏览器-DOM-中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。" class="headerlink" title="一些组件的故事到此结束，其他组件得到卸载浏览器 DOM 中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。"></a>一些组件的故事到此结束，其他组件得到卸载浏览器 DOM 中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。</h3><h3 id="任何-mounted-的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted-的元素都可能接收到不同的属性集。React-的魔力就是这儿，我们实际上需要的正是-React-的这一点！在这一点之前，说实话，我们并不需要-React。"><a href="#任何-mounted-的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted-的元素都可能接收到不同的属性集。React-的魔力就是这儿，我们实际上需要的正是-React-的这一点！在这一点之前，说实话，我们并不需要-React。" class="headerlink" title="任何 mounted 的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted 的元素都可能接收到不同的属性集。React 的魔力就是这儿，我们实际上需要的正是 React 的这一点！在这一点之前，说实话，我们并不需要 React。"></a>任何 mounted 的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted 的元素都可能接收到不同的属性集。React 的魔力就是这儿，我们实际上需要的正是 React 的这一点！在这一点之前，说实话，我们并不需要 React。</h3><h3 id="组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。"><a href="#组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。" class="headerlink" title="组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。"></a>组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。</h3><h2 id="React-组件可以具有私有状态"><a href="#React-组件可以具有私有状态" class="headerlink" title="React 组件可以具有私有状态"></a>React 组件可以具有私有状态</h2><p>以下只适用于类组件。我有没有提到有人叫表象而已的部件 dumb？</p>
<p>状态类是任何 React 类组件中的一个特殊字段。React 检测每一个组件状态的变化，但是为了 React 更加有效，我们必须通过 React 的另一个 API 改变状态字段，这就是我们要学习的另一个 API —— <strong>this.setState</strong>：<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">CounterButton</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  state = &#123;</span><br><span class="line">    clickCounter: <span class="number">0</span>,</span><br><span class="line">    currentTimestamp: <span class="keyword">new</span> <span class="built_in">Date</span>(),</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  handleClick = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">this</span>.setState(<span class="function">(<span class="params">prevState</span>) =&gt;</span> &#123;</span><br><span class="line">     <span class="keyword">return</span> &#123; <span class="attr">clickCounter</span>: prevState.clickCounter + <span class="number">1</span> &#125;;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  componentDidMount() &#123;</span><br><span class="line">   setInterval(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">     <span class="keyword">this</span>.setState(&#123; <span class="attr">currentTimestamp</span>: <span class="keyword">new</span> <span class="built_in">Date</span>() &#125;)</span><br><span class="line">    &#125;, <span class="number">1000</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &lt;button onClick=&#123;<span class="keyword">this</span>.handleClick&#125;&gt;Click&lt;<span class="regexp">/button&gt;</span></span><br><span class="line"><span class="regexp">        &lt;p&gt;Clicked: &#123;this.state.clickCounter&#125;&lt;/</span>p&gt;</span><br><span class="line">        &lt;p&gt;Time: &#123;<span class="keyword">this</span>.state.currentTimestamp.toLocaleString()&#125;&lt;<span class="regexp">/p&gt;</span></span><br><span class="line"><span class="regexp">      &lt;/</span>div&gt;</span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用</span></span><br><span class="line">ReactDOM.render(<span class="xml"><span class="tag">&lt;<span class="name">CounterButton</span> /&gt;</span></span>, mountNode);</span><br></pre></td></tr></table></figure><br>例 13：setState 的 API<br>这可能是最重要的一个例子因为这将是你完全理解 React 基础知识的方式。这个例子之后，还有一些小事情需要学习，但从那时起主要是你和你的 JavaScript 技能。</p>
<p>让我们来看一下例 13，从类开始，总共有两个，一个是一个初始化的有初始值为 0 的 clickCounter 对象和一个从 new Date() 开始的 currentTimestamp。</p>
<p>另一个类是 handleClick 函数，在渲染方法中我们给按钮元素传入 onClick 事件。通过使用 setState 的 handleClick 方法修改了组件的实例状态。要注意到这一点。</p>
<p>另一个我们修改状态的地方是在一个内部的定时器，开始在内部的 componentDidMount 生命周期方法。它每秒钟调用一次并且执行另一个函数调用 this.setState。<br>在渲染方法中，我们使用具有正常读语法的状态上的两个属性（没有专门的 API）。<br>现在，注意我们更新状态使用两种不同的方式： </p>
<p>1.通过传入一个函数然后返回一个对象。我们在 handleClick 函数内部这样做。<br>2.通过传入一个正则对象，我们在在区间回调中这样做。</p>
<p>这两种方式都是可以接受的，但是当你同时读写状态时，第一种方法是首选的（我们这样做）。在区间回调中，我们只向状态写入而不读它。当有问题时，总是使用第一个函数作为参数语法。伴随着竞争条件这更安全，因为 setstate 实际上是一个异步方法。<br>我们应该怎样更新状态呢？我们返回一个有我们想要更新的的值的对象。注意，在调用 setState 时，我们全部都从状态中传入一个属性或者全都不。这完全是可以的因为 setState 实际上 合并 了你通过它（返回值的函数参数）与现有的状态，所以，没有指定一个属性在调用 setState 时意味着我们不希望改变属性（但不删除它）。<br><img src="https://user-gold-cdn.xitu.io/2017/8/14/3508772844b644f46f547ab3ba75e6a3?imageView2/0/w/1280/h/960/format/webp/ignore-error/1" alt="REACT"></p>
<h2 id="React-将要反应"><a href="#React-将要反应" class="headerlink" title="React 将要反应"></a>React 将要反应</h2><p>React 的名字是从状态改变的<strong>反应</strong>中得来的（虽然没有反应，但也是在一个时间表中）。这里有一个笑话，React 应该被命名为Schedule！</p>
<p>然而，当任何组件的状态被更新时，我们用肉眼观察到的是对该更新的反应，并自动反映了浏览器 DOM 中的更新（如果需要的话）。<br>将渲染函数的输入视为两种：</p>
<p>1.通过父元素传入的属性<br>2.以及可以随时更新的内部私有状态</p>
<p>当渲染函数的输入改变时，输出可能也会改变。<br>React 保存了渲染的历史记录，当它看到一个渲染与前一个不同时，它将计算它们之间的差异，并将其有效地转换为在 DOM 中执行的实际 DOM 操作。</p>
<h2 id="React-是你的代码"><a href="#React-是你的代码" class="headerlink" title="React 是你的代码"></a>React 是你的代码</h2><p>您可以将 React 看作是我们用来与浏览器通信的代理。以上面的当前时间戳显示为例。取代每一秒我们都需要手动去浏览器调用 DOM API 操作来查找和更新 <strong>p#timestamp</strong> 元素，我们仅仅改变组件的状态属性，React 做的工作代表我们与浏览器的通信。我相信这就是为什么 React 这么受欢迎的真正原因；我们只是不喜欢和浏览器先生谈话（以及它所说的 DOM 语言的很多方言），并且 React 自愿传递给我们，免费的！</p>
<h2 id="每一个-React-组件都有一个故事：第-2-部分"><a href="#每一个-React-组件都有一个故事：第-2-部分" class="headerlink" title="每一个 React 组件都有一个故事：第 2 部分"></a>每一个 React 组件都有一个故事：第 2 部分</h2><blockquote>
<ul>
<li>现在我们知道了一个组件的状态，当该状态发生变化的时候，我们来了解一下关于这个过程的最后几个概念。</li>
<li>当组件的状态被更新时，或者它的父进程决定更改它传递给组件的属性时，组件可能需要重新渲染。</li>
<li>如果后者发生，React 会调用另一个生命周期方法：componentWillReceiveProps。</li>
<li>如果状态对象或传递的属性改变了，React 有一个重要的决定要做：组件是否应该在 DOM 中更新？这就是为什么它调用另一个重要的生命周期方法 shouldComponentUpdate 的原因 。此方法是一个实际问题，因此，如果需要自行定制或优化渲染过程，则必须通过返回 true 或 false 来回答这个问题。</li>
<li>如果没有自定义 shouldComponentUpdate，React 的默认事件在大多数情况下都能处理的很好。</li>
<li>首先，这个时候会调用另一生命周期的方法：componentWillUpdate。然后，React 将计算新渲染过的输出，并将其与最后渲染的输出进行对比。</li>
<li>如果渲染过的输出和之前的相同，React 不进行处理（不需要和浏览器先生对话）。</li>
<li>如果有不同的地方，React 将不同传达给浏览器，像我们之前看到的那样。</li>
<li>在任何情况下，一旦一个更新程序发生了，无论以何种方式（即使有相同的输出），React 会调用最后的生命周期方法：componentDidUpdate。</li>
</ul>
</blockquote>
<p>生命周期方法是逃生舱口。如果你没有做什么特别的事情，你可以在没有它们的情况下创建完整的应用程序。它们非常方便地分析应用程序中正在发生的事情，并进一步优化 React 更新的性能。</p>
<p>信不信由你，通过上面所学的知识（或部分知识），你可以开始创建一些有趣的 React 应用程序。如果你渴望更多，看看我的 Pluralsight 的 <a href="https://www.pluralsight.com/courses/react-js-getting-started?aid=701j0000001heIoAAI&amp;promo=&amp;oid=&amp;utm_source=google&amp;utm_medium=ppc&amp;utm_campaign=US_Dynamic&amp;utm_content=&amp;utm_term=&amp;gclid=CNOAj_2-j9UCFUpNfgod4V0Fdg" target="_blank" rel="noopener">React.js 入门课程</a>。</p>

            <!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->
            <audio id="audio" loop="1" preload="auto" controls="controls"
                data-autoplay="false">
                <source type="audio/mpeg" src="">
            </audio>
            
            <ul id="audio-list" style="display:none">
                
                
                <li title='0' data-url='/statics/chengdu.mp3'></li>
                
                    
            </ul>
            
            
            
    <div id='gitalk-container' class="comment link"
        data-ae='true'
        data-ci='ec894e2b66f752e8b7fb'
        data-cs='3ccc2e92bb350688fe2c2dc2930189b62622bfb1'
        data-r='blog-comments'
        data-o='TriDiamond'
        data-a='TriDiamond'
        data-d='undefined'
    >Comments</div>


            
            
        </div>
        <div class="sidebar">
            <div class="box animated fadeInRight">
                <div class="subbox">
                    <img src="https://res.cloudinary.com/tridiamond/image/upload/v1573019751/TriDiamond_logo_ui_xeublz.jpg" height=300 width=300></img>
                    <p>张白告丶</p>
                    <span>Think like an artist, develop like an artisan</span>
                    <dl>
                        <dd><a href="https://github.com/zhanghao-web" target="_blank"><span
                                    class=" iconfont icon-github"></span></a></dd>
                        <dd><a href="" target="_blank"><span
                                    class=" iconfont icon-twitter"></span></a></dd>
                        <dd><a href="" target="_blank"><span
                                    class=" iconfont icon-stack-overflow"></span></a></dd>
                    </dl>
                </div>
                <ul>
                    <li><a href="/">149 <p>Articles</p></a></li>
                    <li><a href="/categories">23 <p>Categories</p></a></li>
                    <li><a href="/tags">47 <p>Tags</p></a></li>
                </ul>
            </div>
            
            
            
            <div class="box sticky animated fadeInRight faster">
                <div id="toc" class="subbox">
                    <h4>Contents</h4>
                    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#学习-React-js-比你想象的要简单"><span class="toc-number">1.</span> <span class="toc-text">学习 React.js 比你想象的要简单</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#React-全部都是组件化的"><span class="toc-number">1.1.</span> <span class="toc-text">React 全部都是组件化的</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#JSX-输出的是什么？"><span class="toc-number">1.2.</span> <span class="toc-text">JSX 输出的是什么？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#你可以在-JavaScript-的任何地方使用-JSX"><span class="toc-number">1.3.</span> <span class="toc-text">你可以在 JavaScript 的任何地方使用 JSX</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#你可以使用-JavaScript-类写-React-组件"><span class="toc-number">1.4.</span> <span class="toc-text">你可以使用 JavaScript 类写 React 组件</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-中的事件：两个重要的区别"><span class="toc-number">1.5.</span> <span class="toc-text">React 中的事件：两个重要的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#每一个-React-组件都有一个故事：第-1-部分"><span class="toc-number">1.6.</span> <span class="toc-text">每一个 React 组件都有一个故事：第 1 部分</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#首先，我们定义了一个模板来创建组件中的元素。"><span class="toc-number">1.6.1.</span> <span class="toc-text">首先，我们定义了一个模板来创建组件中的元素。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#然后，我们在某处使用-React。例如，在-render-内部调用其他的组件，或者直接使用-ReactDOM-render。"><span class="toc-number">1.6.2.</span> <span class="toc-text">然后，我们在某处使用 React。例如，在 render 内部调用其他的组件，或者直接使用 ReactDOM.render。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#然后，React-实例化一个对象然后给它设置-props-然后我们可以通过-this-props-访问。这些属性都是我们在第-2-步传入的。"><span class="toc-number">1.6.3.</span> <span class="toc-text">然后，React 实例化一个对象然后给它设置 props 然后我们可以通过 this.props 访问。这些属性都是我们在第 2 步传入的。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#因为这些全部都是-JavaScript，constructor-方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。"><span class="toc-number">1.6.4.</span> <span class="toc-text">因为这些全部都是 JavaScript，constructor 方法将会被调用（如果定义的话）。这是我们称之为的第一个：组件生命周期方法。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#接下来-React-计算渲染之后的输出方法（虚拟-DOM-节点）。"><span class="toc-number">1.6.5.</span> <span class="toc-text">接下来 React 计算渲染之后的输出方法（虚拟 DOM 节点）。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#因为这是-React-第一次渲染元素，React-将会与浏览器连通（代表我们使用-DOM-API）来显示元素。这整个过程称为-mounting。"><span class="toc-number">1.6.6.</span> <span class="toc-text">因为这是 React 第一次渲染元素，React 将会与浏览器连通（代表我们使用 DOM API）来显示元素。这整个过程称为 mounting。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#接下来-React-调用另一个生命周期函数，称为-componentDidMount。我们可以这样使用这个方法，例如：在-DOM-上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的-DOM-都是虚拟的。"><span class="toc-number">1.6.7.</span> <span class="toc-text">接下来 React 调用另一个生命周期函数，称为 componentDidMount。我们可以这样使用这个方法，例如：在 DOM 上做一些我们现在知道的在浏览器中存在的东西。在此生命周期方法之前，我们使用的 DOM 都是虚拟的。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#一些组件的故事到此结束，其他组件得到卸载浏览器-DOM-中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。"><span class="toc-number">1.6.8.</span> <span class="toc-text">一些组件的故事到此结束，其他组件得到卸载浏览器 DOM 中的各种原因。在后一种情况发生时，会调用另一个生命周期的方法，componentWillUnmount。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#任何-mounted-的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted-的元素都可能接收到不同的属性集。React-的魔力就是这儿，我们实际上需要的正是-React-的这一点！在这一点之前，说实话，我们并不需要-React。"><span class="toc-number">1.6.9.</span> <span class="toc-text">任何 mounted 的元素的状态都可能会改变。该元素的父级可能会重新渲染。无论哪种情况，mounted 的元素都可能接收到不同的属性集。React 的魔力就是这儿，我们实际上需要的正是 React 的这一点！在这一点之前，说实话，我们并不需要 React。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。"><span class="toc-number">1.6.10.</span> <span class="toc-text">组价的故事还在继续，但是在此之前，我们需要理解我所说的这种状态。</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-组件可以具有私有状态"><span class="toc-number">1.7.</span> <span class="toc-text">React 组件可以具有私有状态</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-将要反应"><span class="toc-number">1.8.</span> <span class="toc-text">React 将要反应</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#React-是你的代码"><span class="toc-number">1.9.</span> <span class="toc-text">React 是你的代码</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#每一个-React-组件都有一个故事：第-2-部分"><span class="toc-number">1.10.</span> <span class="toc-text">每一个 React 组件都有一个故事：第 2 部分</span></a></li></ol></li></ol>
                </div>
            </div>
            
            
        </div>
    </div>
</div>

    </div>
</div>
    <div id="back-to-top" class="animated fadeIn faster">
        <div class="flow"></div>
        <span class="percentage animated fadeIn faster">0%</span>
        <span class="iconfont icon-top02 animated fadeIn faster"></span>
    </div>
</body>
<footer>
    <p class="copyright" id="copyright">
        &copy; 2020
        <span class="gradient-text">
            张白告丶
        </span>.
        Powered by <a href="http://hexo.io/" title="Hexo" target="_blank" rel="noopener">Hexo</a>
        Theme
        <span class="gradient-text">
            <a href="https://github.com/TriDiamond/hexo-theme-obsidian" title="Obsidian" target="_blank" rel="noopener">Obsidian</a>
        </span>
        <small><a href="https://github.com/TriDiamond/hexo-theme-obsidian/blob/master/CHANGELOG.md" title="v1.4.3" target="_blank" rel="noopener">v1.4.3</a></small>
    </p>
</footer>

<script type="text/javascript" src="https://cdn.bootcss.com/mathjax/2.7.6/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script>
  MathJax.Hub.Config({
    "HTML-CSS": {
      preferredFont: "TeX",
      availableFonts: ["STIX", "TeX"],
      linebreaks: {
        automatic: true
      },
      EqnChunk: (MathJax.Hub.Browser.isMobile ? 10 : 50)
    },
    tex2jax: {
      inlineMath: [
        ["$", "$"],
        ["\\(", "\\)"]
      ],
      processEscapes: true,
      ignoreClass: "tex2jax_ignore|dno",
      skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
    },
    TeX: {
      noUndefined: {
        attributes: {
          mathcolor: "red",
          mathbackground: "#FFEEEE",
          mathsize: "90%"
        }
      },
      Macros: {
        href: "{}"
      }
    },
    messageStyle: "none"
  });
</script>
<script>
  function initialMathJax() {
    MathJax.Hub.Queue(function () {
      var all = MathJax.Hub.getAllJax(),
        i;
      // console.log(all);
      for (i = 0; i < all.length; i += 1) {
        console.log(all[i].SourceElement().parentNode)
        all[i].SourceElement().parentNode.className += ' has-jax';
      }
    });
  }

  function reprocessMathJax() {
    if (typeof MathJax !== 'undefined') {
      MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
    }
  }
</script>



    
<link rel="stylesheet" href="//cdn.bootcss.com/gitalk/1.5.0/gitalk.min.css">

    
<script src="//cdn.bootcss.com/gitalk/1.5.0/gitalk.min.js"></script>



<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="/js/plugin.js"></script>
<script src="/js/obsidian.js"></script>
<script src="/js/jquery.truncate.js"></script>
<script src="/js/search.js"></script>


<script src="//cdn.bootcss.com/typed.js/2.0.10/typed.min.js"></script>


<script src="//cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script>


<script src="//cdnjs.cloudflare.com/ajax/libs/social-share.js/1.0.16/js/social-share.min.js"></script>


<script src="https://cdn.bootcss.com/codemirror/5.48.4/codemirror.min.js"></script>

    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/javascript/javascript.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/css/css.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/xml/xml.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/htmlmixed/htmlmixed.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/clike/clike.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/php/php.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/shell/shell.min.js"></script>


    
<script src="//cdn.bootcss.com/codemirror/5.48.4/mode/python/python.min.js"></script>




    
<script src="/js/busuanzi.min.js"></script>

    <script>
        $(document).ready(function () {
            if ($('span[id^="busuanzi_"]').length) {
                initialBusuanzi();
            }
        });
    </script>



<link rel="stylesheet" href="//cdn.bootcss.com/photoswipe/4.1.3/photoswipe.min.css">
<link rel="stylesheet" href="//cdn.bootcss.com/photoswipe/4.1.3/default-skin/default-skin.min.css">


<script src="//cdn.bootcss.com/photoswipe/4.1.3/photoswipe.min.js"></script>
<script src="//cdn.bootcss.com/photoswipe/4.1.3/photoswipe-ui-default.min.js"></script>


<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>
    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">
        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>
        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">
            <div class="pswp__top-bar">
                <!--  Controls are self-explanatory. Order can be changed. -->
                <div class="pswp__counter"></div>
                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
                <button class="pswp__button pswp__button--share" title="Share"></button>
                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                      <div class="pswp__preloader__cut">
                        <div class="pswp__preloader__donut"></div>
                      </div>
                    </div>
                </div>
            </div>
            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div> 
            </div>
            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>
            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>
            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>
        </div>
    </div>
</div>



    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="//www.googletagmanager.com/gtag/js?id=UA-149874671-1"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', 'UA-149874671-1');
    </script>





<script>
    function initialTyped () {
        var typedTextEl = $('.typed-text');
        if (typedTextEl && typedTextEl.length > 0) {
            var typed = new Typed('.typed-text', {
                strings: ["Think like an artist, develop like an artisan", "艺术家思维去思考问题，工匠创造精神去开发"],
                typeSpeed: 90,
                loop: true,
                loopCount: Infinity,
                backSpeed: 20,
            });
        }
    }

    if ($('.article-header') && $('.article-header').length) {
        $(document).ready(function () {
            initialTyped();
        });
    }
</script>




</html>
